package pers.fulsun.demo.springcloud.helper;

import io.netty.util.internal.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import pers.fulsun.demo.springcloud.utils.SpringUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

@Slf4j
@AllArgsConstructor
@Getter
public class SchedulingRunnable implements Runnable {
    /**
     * 定时任务指定Bean类名
     */
    private String scheBeanName;
    /**
     * 定时任务指定Bean的方法名
     */
    private String scheMethod;

    @Override
    public void run() {
        long startTime = System.currentTimeMillis();
        log.info("执行对应的bean方法：{}.{}(),当前时间：{}", scheBeanName, scheMethod, startTime);
        //利用反射生成对应的bean实例并执行指定方法,指定bean可能涉及数据库或者Spring体系的内容，所以统一从spring容器中获取
        Object target = SpringUtil.getBeanByName(this.getScheBeanName());
        Method method = null;
        //执行实例判空
        if (ObjectUtils.isNotEmpty(target)) {
            try {
                //获取指定方法
                method = target.getClass().getDeclaredMethod(scheMethod);
            } catch (NoSuchMethodException e) {
                if (log.isErrorEnabled()) {
                    log.error(e.getMessage());
                }
            }
            if (ObjectUtils.isNotEmpty(method)) {
                //使该方法可访问可执行
                ReflectionUtils.makeAccessible(method);
                try {
                    method.invoke(target, null);
                } catch (IllegalAccessException e) {
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
            log.info("方法执行完毕，耗时：{}", System.currentTimeMillis() - startTime);
        }
    }

    /**
     * 重写equals方法，否则移除定时任务将出现无法移除的情况，因为无法匹配
     *
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SchedulingRunnable that = (SchedulingRunnable) o;
        return scheBeanName.equals(that.scheBeanName) &&
                scheMethod.equals(that.getScheMethod());
    }

    @Override
    public int hashCode() {
        return Objects.hash(scheBeanName, scheMethod);
    }
}


